<?php

namespace App\Logging;

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\LogRecord;
use Monolog\Utils;

class CustomizeLineFormatter extends LineFormatter
{
    //const NEW_SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: [%request_id%] [%ip%] [%path%] %param% %message% %context% %extra%\n";

    public function format(LogRecord $record): string
    {
        $output = $this->format; // 定义输出格式
        $vars = (new NormalizerFormatter($this->dateFormat))->format($record); // 获取需要格式化的数据
        $requestId = Arr::get(Log::sharedContext(), 'request_id');
        $vars['request_id'] = $requestId; // 单次请求id
        $vars['ip'] = request()->getClientIp();
        $vars['method'] = request()->method();
        $vars['path'] = request()->path();
        $vars['param'] = json_encode(request()->all(), JSON_UNESCAPED_UNICODE);

        foreach ($vars['extra'] as $var => $val) {
            if (strpos($output, '%extra.' . $var . '%') !== false) {
                $output = str_replace('%extra.' . $var . '%', $this->stringify($val), $output);
                unset($vars['extra'][$var]);
            }
        }

        unset($vars['context']['request_id']);

        foreach ($vars['context'] as $var => $val) {
            if (strpos($output, '%context.' . $var . '%') !== false) {
                $output = str_replace('%context.' . $var . '%', $this->stringify($val), $output);
                unset($vars['context'][$var]);
            }
        }

        if ($this->ignoreEmptyContextAndExtra) {
            if (\count($vars['context']) === 0) {
                unset($vars['context']);
                $output = str_replace('%context%', '', $output);
            }

            if (\count($vars['extra']) === 0) {
                unset($vars['extra']);
                $output = str_replace('%extra%', '', $output);
            }
        }

        foreach ($vars as $var => $val) {
            if (strpos($output, '%' . $var . '%') !== false) {
                $output = str_replace('%' . $var . '%', $this->stringify($val), $output);
            }
        }

        // remove leftover %extra.xxx% and %context.xxx% if any
        if (strpos($output, '%') !== false) {
            $output = preg_replace('/%(?:extra|context)\..+?%/', '', $output);
            if ($output === null) {
                $pcreErrorCode = preg_last_error();

                throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
            }
        }

        return $output;
    }
}
